package com.zondy.mapgis.android.activity;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

import android.annotation.TargetApi;
import android.app.ActionBar;
import android.app.Activity;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.support.v4.util.LruCache;
import android.text.Editable;
import android.text.TextWatcher;
import android.text.format.DateUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
import android.view.ViewGroup;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationSet;
import android.view.animation.TranslateAnimation;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

import com.avos.avoscloud.AVException;
import com.avos.avoscloud.AVOSCloud;
import com.avos.avoscloud.AVPersistenceUtils;
import com.avos.avoscloud.AVUtils;
import com.avos.avoscloud.GetDataCallback;
import com.avos.avoscloud.LogUtil;
import com.avos.avoscloud.feedback.Comment;
import com.avos.avoscloud.feedback.Comment.CommentType;
import com.avos.avoscloud.feedback.FeedbackAgent;
import com.avos.avoscloud.feedback.FeedbackThread;
import com.avos.avoscloud.feedback.FeedbackThread.SyncCallback;
import com.avos.avoscloud.feedback.Resources;
import com.zondy.mapgis.android.model.EntityUser;
import com.zondy.mapgis.android.utils.SharedUtils;
import com.zondy.mapgis.android.utils.StringUtils;
import com.zondy.mapgis.explorer.R;

public class ThreadFeedbackActivity extends Activity
{

	FeedbackAgent agent;
	ListView feedbackListView;
	Button sendButton;
	EditText feedbackInput;
	EditText contact;
	FeedbackThread thread;
	FeedbackListAdapter adapter;
	SyncCallback syncCallback;
	ImageView imageButton;
	AtomicBoolean animating = new AtomicBoolean(false);
	private static final int IMAGE_REQUEST = 657843;
	public static final ImageCache cache = new ImageCache(AVOSCloud.applicationContext);

	private EntityUser mUser = null;
	private TextView mTile = null;
	private ImageView mTileBack = null;

	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(Resources.layout.avoscloud_feedback_activity_conversation(this));

		// setupActionBar();
		AVOSCloud.initialize(this, "eNwCJJzcDL43oyCY61Cl7jX9-gzGzoHsz", "POTvM92BpQYTA1uIfjzUtSFu");
		initView();

		agent = new FeedbackAgent(this);
		adapter = new FeedbackListAdapter(this);
		thread = agent.getDefaultThread();
		feedbackListView = (ListView) findViewById(Resources.id.avoscloud_feedback_thread_list(this));
		feedbackListView.setAdapter(adapter);
		sendButton = (Button) findViewById(Resources.id.avoscloud_feedback_send(this));
		imageButton = (ImageView) findViewById(Resources.id.avoscloud_feedback_add_image(this));
		feedbackInput = (EditText) findViewById(Resources.id.avoscloud_feedback_input(this));
		syncCallback = new SyncCallback()
		{

			@Override
			public void onCommentsSend(List<Comment> comments, AVException e)
			{
				LogUtil.avlog.d("send new comments");
				adapter.notifyDataSetChanged();
			}

			@Override
			public void onCommentsFetch(List<Comment> comments, AVException e)
			{
				LogUtil.avlog.d("fetch new comments");
				adapter.notifyDataSetChanged();
			}

		};
		sendButton.setOnClickListener(new OnClickListener()
		{

			@Override
			public void onClick(View v)
			{
				sendButton.setOnClickListener(null);
				String feedbackText = feedbackInput.getText().toString();
				feedbackInput.setText("");
				if (!AVUtils.isBlankString(feedbackText))
				{
					thread.add(new Comment(feedbackText));
					adapter.notifyDataSetChanged();
					feedbackListView.setSelection(feedbackListView.getAdapter().getCount());
					smoothScrollToBottom();
					thread.sync(syncCallback);
				}
				sendButton.setOnClickListener(this);
			}
		});

		imageButton.setOnClickListener(new OnClickListener()
		{
			@Override
			public void onClick(View v)
			{

				if (Build.VERSION.SDK_INT < 19)
				{
					Intent intent = new Intent();
					intent.setType("image/*");
					intent.setAction(Intent.ACTION_GET_CONTENT);
					startActivityForResult(Intent.createChooser(intent,
							getResources().getString(Resources.string.avoscloud_feedback_select_image(ThreadFeedbackActivity.this))), IMAGE_REQUEST);
				}
				else
				{
					Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
					intent.addCategory(Intent.CATEGORY_OPENABLE);
					intent.setType("image/*");
					startActivityForResult(intent, IMAGE_REQUEST);
				}

			}
		});

		feedbackInput.setOnFocusChangeListener(new OnFocusChangeListener()
		{

			@Override
			public void onFocusChange(View v, boolean hasFocus)
			{
				if (hasFocus)
				{
					feedbackListView.setSelection(feedbackListView.getAdapter().getCount());
					smoothScrollToBottom();
				}
			}
		});

		feedbackInput.addTextChangedListener(new TextWatcher()
		{

			@Override
			public void onTextChanged(CharSequence s, int start, int before, int count)
			{
				if (AVUtils.isBlankString(s.toString()) && !animating.get() && imageButton.getVisibility() == View.INVISIBLE)
				{
					Animation a1 = new TranslateAnimation(0, 0, 0, 100);
					Animation a2 = new AlphaAnimation(1, 0.2f);
					AnimationSet set = new AnimationSet(true);
					set.setInterpolator(ThreadFeedbackActivity.this, android.R.interpolator.decelerate_cubic);
					set.addAnimation(a1);
					set.addAnimation(a2);
					set.setDuration(300);
					set.setRepeatMode(Animation.REVERSE);
					set.setAnimationListener(new AnimationListener()
					{

						@Override
						public void onAnimationStart(Animation animation)
						{
							animating.set(true);
						}

						@Override
						public void onAnimationRepeat(Animation animation)
						{
						}

						@Override
						public void onAnimationEnd(Animation animation)
						{
							animating.set(false);
							sendButton.setVisibility(View.INVISIBLE);
						}
					});
					sendButton.startAnimation(set);

					imageButton.setVisibility(View.VISIBLE);
					Animation a3 = new TranslateAnimation(0, 0, -50, 0);
					Animation a4 = new AlphaAnimation(0.2f, 1);
					AnimationSet set2 = new AnimationSet(true);
					set2.setInterpolator(ThreadFeedbackActivity.this, android.R.interpolator.accelerate_decelerate);
					set2.addAnimation(a3);
					set2.addAnimation(a4);
					set2.setDuration(250);
					set2.setRepeatMode(Animation.REVERSE);
					set2.setAnimationListener(new AnimationListener()
					{

						@Override
						public void onAnimationStart(Animation animation)
						{

						}

						@Override
						public void onAnimationRepeat(Animation animation)
						{
							// TODO Auto-generated method stub

						}

						@Override
						public void onAnimationEnd(Animation animation)
						{
							imageButton.setVisibility(View.VISIBLE);
						}
					});
					imageButton.startAnimation(set2);
				}
				else if (!AVUtils.isBlankString(s.toString()) && !animating.get() && sendButton.getVisibility() == View.INVISIBLE)
				{

					Animation a1 = new TranslateAnimation(0, 0, 0, -100);
					Animation a2 = new AlphaAnimation(1, 0.2f);
					AnimationSet set = new AnimationSet(true);
					set.setInterpolator(ThreadFeedbackActivity.this, android.R.interpolator.decelerate_cubic);
					set.addAnimation(a1);
					set.addAnimation(a2);
					set.setDuration(300);
					set.setRepeatMode(Animation.REVERSE);
					set.setAnimationListener(new AnimationListener()
					{

						@Override
						public void onAnimationStart(Animation animation)
						{
							// TODO Auto-generated method stub
							animating.set(true);
						}

						@Override
						public void onAnimationRepeat(Animation animation)
						{
							// TODO Auto-generated method stub

						}

						@Override
						public void onAnimationEnd(Animation animation)
						{
							imageButton.setVisibility(View.INVISIBLE);
							animating.set(false);
						}
					});
					imageButton.startAnimation(set);

					sendButton.setVisibility(View.VISIBLE);
					Animation a3 = new TranslateAnimation(0, 0, 50, 0);
					Animation a4 = new AlphaAnimation(0.2f, 1);
					AnimationSet set2 = new AnimationSet(true);

					set2.setInterpolator(ThreadFeedbackActivity.this, android.R.interpolator.accelerate_decelerate);
					set2.addAnimation(a3);
					set2.addAnimation(a4);
					set2.setDuration(250);
					set2.setRepeatMode(Animation.REVERSE);
					set2.setAnimationListener(new AnimationListener()
					{

						@Override
						public void onAnimationStart(Animation animation)
						{

						}

						@Override
						public void onAnimationRepeat(Animation animation)
						{

						}

						@Override
						public void onAnimationEnd(Animation animation)
						{
							sendButton.setVisibility(View.VISIBLE);
						}
					});
					sendButton.startAnimation(set2);

				}

			}

			@Override
			public void beforeTextChanged(CharSequence s, int start, int count, int after)
			{

			}

			@Override
			public void afterTextChanged(Editable s)
			{

			}
		});

		contact = (EditText) findViewById(Resources.id.avoscloud_feedback_contact(this));
		// 用户名
		mUser = SharedUtils.getInstance().getUserInfo(getApplicationContext());
		if (StringUtils.isNotEmpty(mUser.getUserName()))
		{
			contact.setText(mUser.getUserName());
		}
		if (agent.isContactEnabled())
		{
			// contact.setVisibility(View.VISIBLE);
			if (StringUtils.isNotEmpty(mUser.getUserName()))
			{
				thread.setContact(mUser.getUserName());
			}
			contact.setText(thread.getContact());
			contact.addTextChangedListener(new TextWatcher()
			{

				@Override
				public void afterTextChanged(Editable s)
				{
					if (!AVUtils.isBlankString(s.toString()))
					{
						thread.setContact(s.toString());
					}
				}

				@Override
				public void beforeTextChanged(CharSequence s, int start, int count, int after)
				{

				}

				@Override
				public void onTextChanged(CharSequence s, int start, int before, int count)
				{

				}

			});
		}
		else
		{
			contact.setVisibility(View.GONE);
		}

		thread.sync(syncCallback);
	}

	/**
	 * @param uri The Uri to check.
	 * @return Whether the Uri authority is ExternalStorageProvider.
	 */
	private static boolean isExternalStorageDocument(Uri uri)
	{
		return "com.android.externalstorage.documents".equals(uri.getAuthority());
	}

	/**
	 * @param uri The Uri to check.
	 * @return Whether the Uri authority is DownloadsProvider.
	 */
	private static boolean isDownloadsDocument(Uri uri)
	{
		return "com.android.providers.downloads.documents".equals(uri.getAuthority());
	}

	/**
	 * @param uri The Uri to check.
	 * @return Whether the Uri authority is MediaProvider.
	 */
	private static boolean isMediaDocument(Uri uri)
	{
		return "com.android.providers.media.documents".equals(uri.getAuthority());
	}

	@TargetApi(Build.VERSION_CODES.KITKAT)
	private static String getPath(final Context context, final Uri uri)
	{

		final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;

		// DocumentProvider
		if (isKitKat && DocumentsContract.isDocumentUri(context, uri))
		{
			// ExternalStorageProvider
			if (isExternalStorageDocument(uri))
			{
				final String docId = DocumentsContract.getDocumentId(uri);
				final String[] split = docId.split(":");
				final String type = split[0];

				if ("primary".equalsIgnoreCase(type))
				{
					return Environment.getExternalStorageDirectory() + "/" + split[1];
				}

				// TODO handle non-primary volumes
			}
			// DownloadsProvider
			else if (isDownloadsDocument(uri))
			{

				final String id = DocumentsContract.getDocumentId(uri);
				final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

				return getDataColumn(context, contentUri, null, null);
			}
			// MediaProvider
			else if (isMediaDocument(uri))
			{
				final String docId = DocumentsContract.getDocumentId(uri);
				final String[] split = docId.split(":");
				final String type = split[0];

				Uri contentUri = null;
				if ("image".equals(type))
				{
					contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
				}
				else if ("video".equals(type))
				{
					contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
				}
				else if ("audio".equals(type))
				{
					contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
				}

				final String selection = "_id=?";
				final String[] selectionArgs = new String[] { split[1] };

				return getDataColumn(context, contentUri, selection, selectionArgs);
			}
		}
		// MediaStore (and general)
		else if ("content".equalsIgnoreCase(uri.getScheme()))
		{
			return getDataColumn(context, uri, null, null);
		}
		// File
		else if ("file".equalsIgnoreCase(uri.getScheme()))
		{
			return uri.getPath();
		}

		return null;
	}

	/**
	 * Get the value of the data column for this Uri. This is useful for
	 * MediaStore Uris, and other file-based ContentProviders.
	 * 
	 * @param context The context.
	 * @param uri The Uri to query.
	 * @param selection (Optional) Filter used in the query.
	 * @param selectionArgs (Optional) Selection arguments used in the query.
	 * @return The value of the _data column, which is typically a file path.
	 */
	private static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs)
	{

		Cursor cursor = null;
		final String column = "_data";
		final String[] projection = { column };

		try
		{
			cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
			if (cursor != null && cursor.moveToFirst())
			{
				final int column_index = cursor.getColumnIndexOrThrow(column);
				return cursor.getString(column_index);
			}
		}
		finally
		{
			if (cursor != null)
				cursor.close();
		}
		return null;
	}

	@TargetApi(Build.VERSION_CODES.KITKAT)
	@Override
	public void onActivityResult(int requestCode, int resultCode, Intent data)
	{

		if (IMAGE_REQUEST == requestCode && resultCode == RESULT_OK && data.getData() != null)
		{
			Uri uri = data.getData();
			String filePath = ThreadFeedbackActivity.getPath(this, uri);

			try
			{
				LogUtil.avlog.d("img picked:" + filePath);
				File attachmentFile = new File(filePath);
				thread.add(new Comment(attachmentFile));
				adapter.notifyDataSetChanged();
				feedbackListView.setSelection(feedbackListView.getAdapter().getCount());
				smoothScrollToBottom();
				thread.sync(syncCallback);
				feedbackInput.setText("");
			}
			catch (AVException e)
			{
				e.printStackTrace();
			}
		}
	}

	public void setupActionBar()
	{
		ActionBar actionBar = getActionBar();
		if (actionBar != null)
		{
			actionBar.setCustomView(Resources.layout.avoscloud_feedback_thread_actionbar(this));
			actionBar.setDisplayShowCustomEnabled(true);
			actionBar.setDisplayShowHomeEnabled(false);
			actionBar.setDisplayShowTitleEnabled(false);
			View backButton = actionBar.getCustomView().findViewById(Resources.id.avoscloud_feedback_actionbar_back(this));
			backButton.setOnClickListener(new OnClickListener()
			{
				@Override
				public void onClick(View v)
				{
					onBackPressed();
					finish();
				}
			});
		}
	}

	/**
	 * 初始化窗体
	 */
	public void initView()
	{
		// 透明状态栏
		getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
		// 透明导航栏
		getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);

		mTile = (TextView) findViewById(R.id.title_text);
		mTile.setText("联系我们");
		mTileBack = (ImageView) findViewById(R.id.title_back);
		mTileBack.setOnClickListener(new OnClickListener()
		{
			@Override
			public void onClick(View arg0)
			{
				finish();
			}
		});

	}

	private void smoothScrollToBottom()
	{
		feedbackListView.post(new Runnable()
		{
			@Override
			public void run()
			{
				feedbackListView.smoothScrollToPosition(feedbackListView.getAdapter().getCount());
			}
		});
	}

	public class FeedbackListAdapter extends BaseAdapter
	{

		Context mContext;
		LayoutInflater inflater;

		public FeedbackListAdapter(Context context)
		{
			this.mContext = context;
			inflater = LayoutInflater.from(context);
		}

		@Override
		public int getCount()
		{
			return thread.getCommentsList().size();
		}

		@Override
		public Object getItem(int position)
		{
			return thread.getCommentsList().get(position);
		}

		@Override
		public long getItemId(int position)
		{
			return position;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent)
		{
			final ViewHolder holder;
			if (convertView == null)
			{
				if (this.getItemViewType(position) == 0)
				{
					convertView = inflater.inflate(Resources.layout.avoscloud_feedback_user_reply(ThreadFeedbackActivity.this), null);
				}
				else
				{
					convertView = inflater.inflate(Resources.layout.avoscloud_feedback_dev_reply(ThreadFeedbackActivity.this), null);
				}
				holder = new ViewHolder();
				holder.content = (TextView) convertView.findViewById(Resources.id.avoscloud_feedback_content(ThreadFeedbackActivity.this));
				holder.timestamp = (TextView) convertView.findViewById(Resources.id.avoscloud_feedback_timestamp(ThreadFeedbackActivity.this));
				holder.image = (ImageView) convertView.findViewById(Resources.id.avoscloud_feedback_image(ThreadFeedbackActivity.this));
				convertView.setTag(holder);
			}
			else
			{
				holder = (ViewHolder) convertView.getTag();
			}
			final Comment comment = (Comment) getItem(position);
			if (comment.getAttachment() != null && comment.getAttachment().getUrl() != null)
			{
				holder.content.setVisibility(View.GONE);
				holder.image.setVisibility(View.VISIBLE);
				final OnClickListener imageOnClickListener = new OnClickListener()
				{

					@Override
					public void onClick(View v)
					{
						Intent intent = new Intent();
						intent.setAction(Intent.ACTION_VIEW);
						intent.setDataAndType(Uri.fromFile(ImageCache.getCacheFile(comment.getAttachment().getUrl())), "image/*");
						startActivity(intent);
					}
				};
				Bitmap attachmentCache = cache.getImage(comment.getAttachment().getUrl());
				if (attachmentCache != null)
				{
					holder.image.setImageBitmap(attachmentCache);
					holder.image.setOnClickListener(imageOnClickListener);
				}
				else
				{
					holder.image.setOnClickListener(null);
					comment.getAttachment().getDataInBackground(new GetDataCallback()
					{

						@Override
						public void done(byte[] data, AVException e)
						{
							if (e == null)
							{
								Bitmap attachmentCache = cache.setImage(comment.getAttachment().getUrl(), data);
								holder.image.setImageBitmap(attachmentCache);
								holder.image.setOnClickListener(imageOnClickListener);
							}
						}
					});
				}
			}
			else
			{
				holder.content.setVisibility(View.VISIBLE);
				holder.content.setText(comment.getContent());
				holder.image.setVisibility(View.GONE);
			}
			if (Math.abs(comment.getCreatedAt().getTime() - System.currentTimeMillis()) < 10000)
			{
				holder.timestamp.setText(getResources().getString(Resources.string.avoscloud_feedback_just_now(ThreadFeedbackActivity.this)));
			}
			else
			{
				holder.timestamp.setText(DateUtils.getRelativeTimeSpanString(comment.getCreatedAt().getTime(), System.currentTimeMillis() - 1, 0l,
						DateUtils.FORMAT_ABBREV_ALL));
			}
			return convertView;
		}

		@Override
		public int getViewTypeCount()
		{
			return 2;
		}

		@Override
		public int getItemViewType(int position)
		{
			Comment comment = (Comment) this.getItem(position);
			if (comment.getCommentType().equals(CommentType.USER))
			{
				return 0;
			}
			else
			{
				return 1;
			}
		}
	}

	public class ViewHolder
	{
		TextView content;
		TextView timestamp;
		ImageView image;
	}

	public static class ImageCache
	{
		LruCache<String, Bitmap> bitmapCache;
		static final int cacheSize = 20;
		Context context;

		public ImageCache(Context context)
		{
			this.context = context;
			bitmapCache = new LruCache<String, Bitmap>(cacheSize);
		}

		static String getFileName(String fileUrl)
		{
			Uri uri = Uri.parse(fileUrl);
			return uri.getLastPathSegment();
		}

		public static File getCacheFile(String fileName)
		{
			File imgCacheDir = new File(AVOSCloud.applicationContext.getExternalCacheDir(), "img");
			if (!imgCacheDir.exists())
			{
				imgCacheDir.mkdirs();
			}

			return new File(imgCacheDir, getFileName(fileName));
		}

		static File getCacheThumbnailFile(String fileName)
		{
			File imgCacheDir = new File(AVOSCloud.applicationContext.getExternalCacheDir(), "img");
			if (!imgCacheDir.exists())
			{
				imgCacheDir.mkdirs();
			}
			return new File(imgCacheDir, getFileName(fileName) + ".tn");
		}

		public Bitmap getImage(String key)
		{
			Bitmap cacheBitmap = bitmapCache.get(key);
			if (cacheBitmap == null)
			{
				cacheBitmap = BitmapFactory.decodeFile(getCacheThumbnailFile(key).getAbsolutePath());
			}
			return cacheBitmap;
		}

		public Bitmap setImage(String key, byte[] data)
		{
			OutputStream os = null;
			OutputStream thumbnailOS = null;
			byte[] imageData = null;
			Bitmap thumbnail = null;
			try
			{
				Bitmap tempBM = Bitmap.createScaledBitmap(BitmapFactory.decodeByteArray(data, 0, data.length), 150, 150, false);
				ByteArrayOutputStream baos = new ByteArrayOutputStream();
				tempBM.compress(Bitmap.CompressFormat.JPEG, 100, baos);
				imageData = baos.toByteArray();

				os = new FileOutputStream(getCacheFile(key), true);
				os.write(data);
				thumbnailOS = new FileOutputStream(getCacheThumbnailFile(key), true);
				thumbnailOS.write(imageData);

				thumbnail = BitmapFactory.decodeByteArray(imageData, 0, imageData.length);
			}
			catch (FileNotFoundException e)
			{
				e.printStackTrace();
			}
			catch (IOException e)
			{
				e.printStackTrace();
			}
			finally
			{
				AVPersistenceUtils.closeQuietly(os);
				AVPersistenceUtils.closeQuietly(thumbnailOS);
			}
			return thumbnail;
		}
	}

}
